﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Data;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;

namespace n2loc
{
    //proc the DDR3, DDR4 LOC 
    public class DDRX_LOC
    {




        public List<Tuple<string, string>> netPortMap;

        /// <summary>
        /// 将配置文件中的配置信息装载到每个TextBox
        /// </summary>
        /// <param name="fileName">配置文件路径</param>
        /// <returns>返回读取了配置数据的List</returns>

        public List<Tuple<string, string>> LoadConfigFile(string filePath)
        {


            FileStream fs = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            StreamReader sr = new StreamReader(fs, Encoding.Default);

            //记录每次读取的一行记录
            string strLine = "";
            //记录每行记录中的各字段内容
            string[] aryLine = null;

            this.netPortMap = new List<Tuple<string, string>>();

            string netName, portName;
            while ((strLine = sr.ReadLine()) != null && strLine != "")
            {
                if (strLine != ";")
                {
                    //每行只有一个逗号
                    aryLine = strLine.Split(',');
                    netName = aryLine[0].Replace(" ", "");
                    portName = aryLine[1].Replace(" ", "");
                    Tuple<string, string> tuple_temp = new Tuple<string, string>(netName, portName);
                    netPortMap.Add(tuple_temp);


                }
            }


            sr.Close();
            fs.Close();

            return netPortMap;
        }

        /// 保存配置文件
        /// 
        public void SaveConfigFile(string filePath)
        {

        }
    }
    public class N2LOC
    {
        public enum N2LOC_MODE { COMMON, DDR3, DDR4 };
        public enum SEARCH_MODE { NET_MODE, LOC_MODE};
        public N2LOC_MODE n2loc_mode;
        public SEARCH_MODE search_mode;

        public string currentDir;
        public string currentFile;

        public string ddr3_configFilePath;
        public string ddr4_configFilePath;

        public DataTable dt_afterImport;
        public DataTable dt_afterSearch;

        public N2LOC()
        {
            n2loc_mode = N2LOC_MODE.COMMON;
            InitDataTable_afterSearch();


        }

        public void InitDataTable_afterSearch()
        {
            dt_afterSearch = new DataTable();
            DataColumn netName = new DataColumn("NetName");
            DataColumn chipAndPinName = new DataColumn("chipAndPinName");
            dt_afterSearch.Columns.Add(netName);
            dt_afterSearch.Columns.Add(chipAndPinName);
            

        }

    }
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.WindowState = WindowState.Maximized;
        }

        

        private void ImportCSVFile(object sender, RoutedEventArgs e)
        {
            string filePath = openFile();
            //read data from file
           
            n2loc_i.dt_afterImport = LoadCSV(filePath);

            listView.ItemsSource = n2loc_i.dt_afterImport.DefaultView;

        }



        N2LOC n2loc_i = new N2LOC();
        DDRX_LOC ddr3_loc = new DDRX_LOC();


        public string openFile()
        {
            Microsoft.Win32.OpenFileDialog openFile = new Microsoft.Win32.OpenFileDialog();
            //openFile.InitialDirectory = "D://LCPfiles//TASKS//23suo_highsppedAdc//";
            openFile.Filter = "CSV Flile(*.csv)|*.csv";
            //openFile.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            openFile.Multiselect = false;
            if (openFile.ShowDialog() == false) return "err";
            var filePath = openFile.FileName;

            string fileType = System.IO.Path.GetExtension(filePath);
            if (string.IsNullOrEmpty(fileType)) return "err";
            FileInfo fileinfo = new FileInfo(openFile.SafeFileName);

            n2loc_i.currentDir = System.IO.Path.GetDirectoryName(filePath);
            // dirInfo.currentFilePath = System.IO.Path.GetFileNameWithoutExtension(filePath);

            n2loc_i.ddr3_configFilePath = Directory.GetCurrentDirectory() + "\\ddr3_config.ini";
            n2loc_i.ddr4_configFilePath = Directory.GetCurrentDirectory() + "\\ddr4_config.ini";



            return filePath;
        }

        /// <summary>
        /// 将CSV文件的数据读取到DataTable中
        /// </summary>
        /// <param name="fileName">CSV文件路径</param>
        /// <returns>返回读取了CSV数据的DataTable</returns>
        public static DataTable LoadCSV(string filePath)
        {
            //Encoding encoding = System.Data.Common.GetType(filePath); //Encoding.ASCII;//
            DataTable dt = new DataTable();
            FileStream fs = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);

            //StreamReader sr = new StreamReader(fs, Encoding.UTF8);
            StreamReader sr = new StreamReader(fs, Encoding.Default);
            //string fileContent = sr.ReadToEnd();
            //encoding = sr.CurrentEncoding;
            //记录每次读取的一行记录
            string strLine = "";
            //记录每行记录中的各字段内容
            string[] aryLine = null;
            string[] tableHead = null;
            //标示列数
            int columnCount = 0;
            //标示是否是读取的第一行
            bool IsFirst = true;
            //逐行读取CSV中的数据
            DataColumn netName = new DataColumn("NetName");
            DataColumn chipAndPinName = new DataColumn("chipAndPinName");
            dt.Columns.Add(netName);
            dt.Columns.Add(chipAndPinName);
            columnCount = 2;

            //
            while ((strLine = sr.ReadLine()) != null)
            {
                if (strLine.Contains('.'))
                {

                    aryLine = strLine.Split(',');
                    DataRow dr = dt.NewRow();
                    if (aryLine[1] != "")
                    {
                        for (int j = 0; j < columnCount; j++)
                        {
                            dr[j] = aryLine[j];
                        }
                        dt.Rows.Add(dr);
                    }

                }
                   
            }


            sr.Close();
            fs.Close();
            return dt;
        }
        /// <summary>
        /// 配置后则开始处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GenerateXDC(object sender, RoutedEventArgs e)
        {

            if (n2loc_i.ddr3_configFilePath == null)
                MessageBox.Show("ddr3_configFilePath Path null err !!");
            else
                DDR3_Process();
        }
        /// <summary>
        /// DDR3流程
        /// 
        /// </summary>
        public void DDR3_Process()
        {
            ddr3_loc.LoadConfigFile(n2loc_i.ddr3_configFilePath);

            //搜索
            //展示

        }
        /// <summary>
        /// 在3中处理模式中选择
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SetProcessMode(object sender, RoutedEventArgs e)
        {
            RadioButton rdbtn = (RadioButton)sender;
            switch(rdbtn.Content)
            {
                case ("普通模式"):
                    n2loc_i.n2loc_mode = N2LOC.N2LOC_MODE.COMMON;
                    //button2.Visibility = Visibility.Hidden;

                    break;

                case ("DDR3"):
                    n2loc_i.n2loc_mode = N2LOC.N2LOC_MODE.DDR3;
                    //button2.Visibility = Visibility.Visible;

                    break;
                case ("DDR4"):
                    n2loc_i.n2loc_mode = N2LOC.N2LOC_MODE.DDR4;
                    //button2.Visibility = Visibility.Visible;

                    break;
                case ("Pin 位置"):
                    n2loc_i.search_mode = N2LOC.SEARCH_MODE.NET_MODE;
                    break;

                case ("网络名"):
                    n2loc_i.search_mode = N2LOC.SEARCH_MODE.LOC_MODE;
                    break;
            }
        }
        /// <summary>
        /// 搜索指定的网络名或者Pin位置，并展示在listview中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SearchNetOrLOC(object sender, RoutedEventArgs e)
        {
            string keyWord = textBox1.Text;
            if (keyWord == "" || n2loc_i.dt_afterImport == null )
            {
                //appendLog("查询空字符");
                return;
            }
                
            else
            {
                if (n2loc_i.dt_afterSearch != null)
                    n2loc_i.dt_afterSearch.Clear();
                string strToSearch, partDescribeString;
                UInt32 resultCount = 0;

                if(keyWord=="*")
                {
                    foreach (DataRow dr in n2loc_i.dt_afterImport.Rows)
                    {                       
                            n2loc_i.dt_afterSearch.Rows.Add(dr.ItemArray);
                            resultCount = resultCount + 1;
 
                    }
                }
                else
                {
                    foreach (DataRow dr in n2loc_i.dt_afterImport.Rows)
                    {
                        if (n2loc_i.search_mode == N2LOC.SEARCH_MODE.NET_MODE)
                            strToSearch = dr["NetName"].ToString();
                        else
                            strToSearch = dr["chipAndPinName"].ToString();

                        partDescribeString = dr["chipAndPinName"].ToString();

                        if (strToSearch.Contains(keyWord))
                        {
                            //判断搜索结果中的LOC描述中是否包含RC元件，如果有则将其替换为另一端的Part.LOC描述

                            HasRCPart(partDescribeString);

                            n2loc_i.dt_afterSearch.Rows.Add(dr.ItemArray);
                            resultCount = resultCount + 1;
                        }


                    }
                }
               

                string logLine;
                
                if (n2loc_i.search_mode == N2LOC.SEARCH_MODE.NET_MODE)                 
                    logLine = "Search " + "'" + keyWord + "'" + " for Net, get results:" + resultCount.ToString();
                else
                    logLine = "Search " + "'" + keyWord + "'" + " for LOC, get results:" + resultCount.ToString();


                appendLog(logLine);

                listView.ItemsSource = n2loc_i.dt_afterSearch.DefaultView;
            }
            
        }
        /// <summary>
        /// 判断搜索结果中的LOC描述中是否包含RC元件
        /// 
        /// </summary>
        /// <param name="partDescribeString"></param>
        /// <returns></returns>
        public bool HasRCPart(string partDescribeString)
        {
            bool b_hasRC = false;
            bool b_hasR = false;
            bool b_hasC = false;

            //电容命名， C开头加数字
            Regex rgx = new Regex(@"\bC\d");
            
            string[] arry = partDescribeString.Split(' ');
            string rc_name=null, rc_name_thispin = null;
            foreach (string part in arry)
            {

                if (part.IndexOf('.')!=-1)
                {
                    rc_name = part.Substring(0, part.IndexOf('.'));
                    rc_name_thispin = part.Substring(part.IndexOf('.')+1, 1);
                    
                    b_hasRC = rgx.IsMatch(rc_name);
                    if(b_hasRC)
                    {

                        if (rc_name_thispin)
                            break;
                    }
                        
                }
            }

            //搜索RC器件
            SearchRCDeeper(rc_name, rc_name_thispin);

            return b_hasRC;
        }
        /// <summary>
        /// 如果一个Net通过电容或电阻连接到另一个网络，则找到该网络连接的其它引脚, 并替换此RC元件的描述字符串
        /// </summary>
        /// <param name="RC_Name"></param>
        public string SearchRCDeeper(string RC_Name, string rc_name_pin)
        {
            string netName, newLOCDescription = null, anotherPinDescript = null;

            foreach (DataRow dr in n2loc_i.dt_afterImport.Rows)
            {

                netName = dr["chipAndPinName"].ToString();


                if (netName.Contains(RC_Name) && !netName.Contains(rc_name_pin))
                {
                    string[] arry = netName.Split(' ');
                    if (arry.Length < 10)
                        newLOCDescription = netName;
                    


                }


                

            }
            return anotherPinDescript;
        }
        /// <summary>
        /// 在右侧显示操作日志
        /// </summary>
        /// <param name="logLine"></param>
        public void appendLog(string logLine)
        {
            textBox.AppendText(logLine);
            textBox.AppendText("\n\r");
        }
        ////寻找网络名称
        //private Tuple<string, string, string, int> findNetNameInMap(DataRow dr)
        //{
        //    Tuple<string, string, string, int> answer = null;
        //    string netName;
        //    for (int index = 0; index < netPortMap.Count; index++)
        //    {
        //        netName = dr["NetName"].ToString();
        //        if (netName.Contains(netPortMap[index].Item1.ToString()))
        //        {
        //            if (netName.Contains(netPortMap[13].Item1.ToString()))
        //            {
        //                answer = new Tuple<string, string, string, int>(netName,
        //                                                       netPortMap[13].Item1.ToString(),
        //                                                       netPortMap[13].Item2.ToString(),
        //                                                       13);
        //            }
        //            else
        //            {
        //                answer = new Tuple<string, string, string, int>(netName,
        //                                                       netPortMap[index].Item1.ToString(),
        //                                                       netPortMap[index].Item2.ToString(),
        //                                                       index);
        //            }

        //            return answer;

        //        }



        //    }
        //    return answer;

        //}
    }
}
